package br.mikhas.lab.scanner;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import br.mikhas.util.Assert;
import br.mikhas.util.ExceptionUtils;

public class ReaderStream implements CharStream {

	private int position;
	private StringBuilder builder = new StringBuilder();
	private Reader reader;

	public ReaderStream(File file) {
		try {
			reader = new FileReader(file);
		} catch (FileNotFoundException e) {
			ExceptionUtils.throwWrapped(e);
		}
	}

	public ReaderStream(InputStream stream) {
		reader = new InputStreamReader(stream);
	}

	public ReaderStream(Reader reader) {
		Assert.notNull(reader);
		this.reader = reader;
	}

	public int currentPosition() {
		return position;
	}

	private void checkRange(int index) {
		int len = builder.length();
		if (len < (++index)) {
			char[] buff = new char[Math.max(5, len * index)];

			try {
				int count = reader.read(buff);
				if (count > 0)
					builder.append(buff, 0, count);
			} catch (IOException e) {
				ExceptionUtils.throwWrapped(e);
			}

		}
	}

	@Override
	public String getSection(int start, int end) {
		checkRange(end);
		return builder.substring(start, end);
	}

	@Override
	public boolean hasNext() {
		checkRange(position);
		return this.position < builder.length();
	}

	@Override
	public char nextChar() {
		checkRange(position);
		char c = builder.charAt(position);
		position++;
		return c;
	}

	@Override
	public void setPosition(int pos) {
		this.position = pos;
	}

}
